package cn.com.dhcc.turbo.service.test;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import cn.com.dhcc.app.core.exception.ServiceException;
import cn.com.dhcc.app.core.handler.compresshandler.CompressResult;
import cn.com.dhcc.app.core.handler.compresshandler.CompressService;
import cn.com.dhcc.app.core.handler.compresshandler.CompressServiceFactory;
import cn.com.dhcc.app.core.handler.compresshandler.CompressStatic.COMPRESS_ALGORITHM;
import cn.com.dhcc.app.core.handler.encrypthandler.EncryptResult;
import cn.com.dhcc.app.core.handler.encrypthandler.EncryptService;
import cn.com.dhcc.app.core.handler.encrypthandler.EncryptServiceFactory;
import cn.com.dhcc.app.core.handler.encrypthandler.EncryptStatic.ENCRYPT_ALGORITHM;
import cn.com.dhcc.app.core.service.Log;
import cn.com.dhcc.app.core.service.Log.LOGTYPE;
import cn.com.dhcc.app.core.util.CollectionUtil;
import cn.com.dhcc.app.core.util.Status;
import cn.com.dhcc.app.core.util.StrUtil;
import cn.com.dhcc.app.core.util.UUIDGenerator;
import cn.com.dhcc.app.core.util.XstreamUtil;
import cn.com.dhcc.app.pub.core.consts.AppConst;
import cn.com.dhcc.app.pub.core.consts.AppConst.ExchDataType;
import cn.com.dhcc.app.pub.core.consts.AppConst.PostheadStatus;
import cn.com.dhcc.app.pub.core.consts.AppIocBean;
import cn.com.dhcc.app.pub.core.tag.AppTagEl;
import cn.com.dhcc.turbo.entity.api.OrderResp;
import cn.com.dhcc.turbo.entity.api.Posthead;
import cn.com.dhcc.turbo.entity.api.ProcessInfo;
import cn.com.dhcc.turbo.entity.api.Processes;
import cn.com.dhcc.turbo.entity.api.RouteEntry;
import cn.com.dhcc.turbo.entity.api.RouteLog;
import cn.com.dhcc.turbo.entity.api.SendResp;
import cn.com.dhcc.turbo.entity.exch.SendFileData;
import cn.com.dhcc.turbo.entity.registry.AdapterBase;
import cn.com.dhcc.turbo.entity.registry.AdapterInfo;
import cn.com.dhcc.turbo.entity.registry.FtpUser;
import cn.com.dhcc.turbo.entity.registry.NodeInfo;
import cn.com.dhcc.turbo.service.exch.TurboCompressFilter;
import cn.com.dhcc.turbo.service.exch.TurboEncryptFilter;
import cn.com.dhcc.turbo.service.exch.exhmgr.FtpUserService;
import cn.com.dhcc.turbo.service.exch.filedata.SendFileDataService;
import cn.com.dhcc.turbo.service.registry.BaseInfoService;
import cn.com.dhcc.turbo.service.registry.LocalConfCallBack;


/**
 * 测试适配器验证两个节点交换通道是否通畅
 * @author Administrator
 *
 */
@Service
public class NodeExchTestServiceImpl implements NodeExchTestService{
	@Autowired
	@Qualifier(AppIocBean.BASE_INFO_SERVICEIMPL_BEAN)
	private BaseInfoService baseInfoService;
	@Autowired
	private LocalConfCallBack callback;
	@Autowired
	private SendFileDataService sendFileDataService;
	private Logger logger = Log.getLogger(LOGTYPE.QUARTZJOB);
	//测试适配器是否初始化
    private  boolean isInit=false;
    
    public boolean isInit() {
		return isInit;
	}
	@Autowired
	private FtpUserService ftpUserService;
	//用户上传到ftp服务器的文件目录。该目录是相对目录,存在用户自身目录下
	private static final String uploadmetadataDir = AppConst.FILEDATA_UPLOADMETADATA_DIR;
	//大文件存放的公共目录。
	private static final String globalUploadmetadataDir =AppConst.FILEDATA_GLOBALUPLOADMETADATA_DIR;
	public AdapterInfo getAdapterInfo() throws ServiceException {
		NodeInfo localInfo=baseInfoService.getCurrentNodeInfo();
		AdapterInfo adapter=new AdapterInfo();
		adapter.setId(TEST_ADAPTER_ID);//id
		adapter.setAdapterCode(TEST_ADAPTER_CODE);//code
		adapter.setAdapterName(TEST_DAPATER_NAME);//name
		adapter.setAuthCode(TEST_ADAPTER_AUTHORIZATION);//author
		adapter.setIslocal("1");
		adapter.setWsdlUrl(localInfo.getInstallUrl()+"/"+TEST_ADAPTER_URL);
		return adapter;
	}
	
	@Override
	public AdapterBase getAdapterBase() throws ServiceException {
	    AdapterBase base=new AdapterBase();
	    base.setId(TEST_ADAPTER_ID);
	    base.setAdapterCode(TEST_ADAPTER_CODE);
	    base.setAdapterName(TEST_DAPATER_NAME);
	    base.setDataCode("888888");
	    return base;
	}
	
	public void init() {
		try {
			NodeInfo localInfo=baseInfoService.getCurrentNodeInfo();
			if (localInfo==null) {//节点未初始化
				return;
			}
			AdapterInfo a=getAdapterInfo();
			
			//检测是否初始化
			FtpUser user = ftpUserService.get(a.getAdapterCode());
			if (user!=null) {
				isInit=true;//初始化标志
			}
			
			if (!isInit) {
				callback.onAdapterRegist(a);
				isInit=true;
			}
		} catch (ServiceException e) {
			logger.error("初始化测试适配器出现异常", e);
		}
	}
	public boolean isTest(String postheadXml,String authCode){
		 try {
				Posthead posthead = XstreamUtil.toObject(Posthead.class,postheadXml);
				if (authCode.equals(TEST_ADAPTER_AUTHORIZATION)&& posthead.getFrom()!=null && posthead.getFrom().getNodecode()!=null && posthead.getFrom().getNodecode().equals(TEST_ADAPTER_CODE)) {
					return true;
				}
		 } catch (Exception e) {
			 return false;
		 }
		
		return false;
	}
	@Override
	public Status isValidate(String postheadXml) {
		String msg="";
		Status status=Status.getInstance();
		if (StrUtil.isBlank(postheadXml)) {
            msg = "posthead参数不能为空";
            status.setSuccess(false);
            status.setMsg(msg);
            status.setData("-1");
            return status;
        }
        try {
			Posthead posthead = XstreamUtil.toObject(Posthead.class,postheadXml);
			
			//节点是否初始化验证
			 NodeInfo localNode=baseInfoService.getCurrentNodeInfo();
	         if (localNode==null) {
				msg = "节点还未完成初始化，请稍后再发送数据..";
				status.setSuccess(false);
				status.setMsg(msg);
				return status;
			 }
	         
	         //验证头信息
	 		if (posthead == null) {
	 			msg = "解析pohsthead头信息出错";
	 			status.setSuccess(false);
	 			status.setMsg(msg);
	 			return status;
	 		}
	 		
	 		//from非空验证
	 		if (posthead.getFrom() == null) {
	 			msg = "解析pohsthead头信息出错，发送信息posthead/from不能为空";
	 			status.setSuccess(false);
	 			status.setMsg(msg);
	 			return status;
	 		}
	 		
	 		//from/nodecode非空验证
			if (StrUtil.isBlank(posthead.getFrom().getNodecode())) {
				msg = "解析pohsthead头信息出错，发送头信息中posthead/from/nodecode参数不能为空";
				status.setSuccess(false);
				status.setMsg(msg);
				return status;
			}
			
			
			//from/Adaptorcode非空验证
			if (posthead.getFrom().getAdaptorcode() == null) {
				msg = "解析pohsthead头信息出错，数据类型posthead/from/adaptorcode不能为空";
				status.setSuccess(false);
				status.setMsg(msg);
				return status;
			}
			
			//to非空验证
			if (!CollectionUtil.hasElement(posthead.getToList())) {
				msg = "解析pohsthead头信息出错，接收信息posthead/to不能为空";
				status.setSuccess(false);
				status.setMsg(msg);
				return status;
			}
			
			//to/nodecode非空验证
			for (RouteEntry to : posthead.getToList()) {
				if (StrUtil.isBlank(to.getNodecode())) {
					msg = "解析pohsthead头信息出错，接收信息中posthead/to/nodecode参数不能为空";
					status.setSuccess(false);
					status.setMsg(msg);
					return status;
				}
				
				
				if (to.getNodecode().length()!=posthead.getFrom().getNodecode().length()) {
					msg = "解析pohsthead头信息出错，接收信息中posthead/to/nodecode参数格式不正确";
					status.setSuccess(false);
					status.setMsg(msg);
					return status;
				}
			}
			
			//attachments非空验证
			if (posthead.getAttachments()==null) {
				msg = "解析pohsthead头信息出错，发送头信息中posthead/attachments参数不能为空";
				status.setSuccess(false);
				status.setMsg(msg);
				return status;
			}
			
			//attachment非空验证
			if (posthead.getAttachments().getAttachment()==null || posthead.getAttachments().getAttachment().isEmpty()) {
				msg = "解析pohsthead头信息出错，发送头信息中posthead/attachments/attachment参数不能为空";
				status.setSuccess(false);
				status.setMsg(msg);
				return status;
			}
			
			//attachment非空验证
			boolean flag=false;
			for (String att : posthead.getAttachments().getAttachment()) {
				if (att!=null && !att.trim().equals("")) {
					flag=true;
					break;
				}
			}
			if (!flag) {
				msg = "解析pohsthead头信息出错，发送头信息中posthead/attachments/attachment没有包含文件信息";
				status.setSuccess(false);
				status.setMsg(msg);
				return status;
			}
			
			//验证适配器是否是测试适配器
			if (!TEST_ADAPTER_CODE.equals(posthead.getFrom().getAdaptorcode())) {
				msg = "校验pohsthead头信息失败，发送适配器["+posthead.getFrom().getAdaptorcode()+"]并非测试适配器";
				status.setSuccess(false);
				status.setMsg(msg);
				return status;
			}
			
			//节点有效性验证
			NodeInfo nodeInfo=baseInfoService.getNodeInfoByCode(posthead.getFrom().getNodecode());
			if (nodeInfo==null) {
				msg = "校验pohsthead头信息失败，发送节点["+posthead.getFrom().getNodecode()+"]未在平台注册";
				status.setSuccess(false);
				status.setMsg(msg);
				return status;
			}
			if (!nodeInfo.getNodeCode().equals(localNode.getNodeCode())) {
				msg = "校验pohsthead头信息失败，发送节点["+posthead.getFrom().getNodecode()+"]不是当前节点";
				status.setSuccess(false);
				status.setMsg(msg);
				return status;
			}
			
			//如果能查到nodecode说明，非跨网传输，否则跨网传输
			for (int i=0;i<posthead.getToList().size();i++) {
				RouteEntry to = posthead.getToList().get(i);
				if (posthead.getFrom().getNodecode().substring(6, 7).equals(to.getNodecode().substring(6, 7))) {//同网段的必须判断接收节点也存在
					NodeInfo toNodeInfo=baseInfoService.getNodeInfoByCode(to.getNodecode());
					if (toNodeInfo==null) {
						msg = "校验pohsthead头信息失败，接收节点["+to.getNodecode()+"]未在平台注册";
						status.setSuccess(false);
						status.setMsg(msg);
						return status;
					}
				}
			}
			 msg = "校验成功";
	        status.setSuccess(true);
	        status.setMsg(msg);
	        status.setData(posthead);
	        return status;
			
		} catch (Exception e) {
			msg = "解析posthead头信息出错:" + postheadXml + ">>>cause:" + e.fillInStackTrace();
			status.setSuccess(false);
            status.setMsg(msg);
            status.setData("-1");
            return status;
		}
	}

	@Override
	public String storeDB(String postheadXml,String authCode) {
		String groupId=UUIDGenerator.getUUID();
	
		SendResp sendResp=new SendResp();
		String msg="";
		NodeInfo localNode=null;
		
       try {
    		
   		//授权码验证 
   		if (!getAdapterInfo().getAuthCode().equals(authCode)) {
   		//发送响应
   			sendResp.setGroupId(groupId);
   			sendResp.setStatus(PostheadStatus.BAD_REQUEST.value());
   			sendResp.setMessage("授权码:"+authCode+"无效,请确认测试适配器的授权码");
   			sendResp.setDate(AppConst.dtFormat.format(new Date()));
   			return XstreamUtil.toXml(sendResp);
   		}
   		Status status=isValidate(postheadXml);
   		localNode=baseInfoService.getCurrentNodeInfo();
   		if (!status.isSuccess()) {
   			//发送响应
   			sendResp.setGroupId(groupId);
   			sendResp.setStatus(PostheadStatus.BAD_REQUEST.value());
   			sendResp.setMessage(status.getMsg());
   			sendResp.setDate(AppConst.dtFormat.format(new Date()));
   			return XstreamUtil.toXml(sendResp);
   		}
   		
   		//入库
   		//获取头文件信息
   		Posthead posthead = (Posthead) status.getData();
   		List<RouteEntry> toList = posthead.getToList();
   		RouteEntry from = posthead.getFrom();
   		AdapterBase adapterBase=getAdapterBase();
   		//针对一个xml文件的全部响应信息
   		List<SendFileData> fileDataList = new ArrayList<SendFileData>();

   		List<String> attachments = posthead.getAttachments().getAttachment();
   		String filepaths = "";
   		String storepaths = "";
   		long size = 0;
   		
   		FtpUser user = ftpUserService.get(from.getAdaptorcode());
   		String home = user.getHomedirectory();
   		File uploadmetadir = new File(home, uploadmetadataDir);
   		File globaluploalpath = new File(globalUploadmetadataDir, AppConst.dFormat.format(new Date()));
   		boolean renamefile = false;
   		String renamemessage = "";
   		
   		//压缩处理
   		CompressService compressService = CompressServiceFactory.createCompressService(COMPRESS_ALGORITHM.JAVA_GZIP);
   		//加密处理
   		//解密处理
   		EncryptService encryptService = EncryptServiceFactory.createEncryptService(ENCRYPT_ALGORITHM.DES);
   		
   		Processes pes=new Processes();//处理文件
   		List<ProcessInfo> processInfos=new ArrayList<ProcessInfo>();
   		for (int i = 0; i < attachments.size(); i++) {
   			String attachment = attachments.get(i);
   			while (attachment.indexOf("/") == 0 || attachment.indexOf("\\") == 0) {
   				attachment = attachment.substring(1);//去掉首字母的"/"
   			}
   			File file = new File(uploadmetadir, attachments.get(i));
   			size += file.length();
   			String filename = attachments.get(i);
   			int j = filename.lastIndexOf(".");
   			String suffix = "";
   			if (j != -1) {
   				suffix = filename.substring(j);
   			}
   			//压缩处理
   			CompressResult<String> result = compressService.compress(file,new TurboCompressFilter(ExchDataType.FILE_DATA, null),true);
   			ProcessInfo pi=new ProcessInfo();
   			String compress="0";
   			if (result.isCommpressed()) {
   				compress="1";
   				file=new File(result.getCommpressResultObj());//文件指向压缩文件
   				pi.setCompressfile(file.getName());
   			}
   			pi.setCompress(compress);
   			
   			//加密处理dataCategoryEncryptEnabbled
   			boolean isEncrypt=false;
   			String seed=encryptService.randomSeed(posthead.getFrom().getNodecode()+posthead.getFrom().getAdaptorcode());//加密秘钥
   			EncryptResult<String> sresult=  encryptService.encryptFile(seed,file.getAbsolutePath(),new TurboEncryptFilter(ExchDataType.FILE_DATA, null,isEncrypt),true);
   			String encrypt="0";//加密标志
   			if (sresult.isEncrypted()) {
   				encrypt="1";
   				file=new File(sresult.getEncryptResultObj());//文件指向加密文件
   				pi.setEncryptfile(file.getName());
   			}
   			pi.setEncrypt(encrypt);
   			
   			processInfos.add(pi);
   			
   			
   			String uuid = UUIDGenerator.getUUID();
   			if (globaluploalpath.exists() || globaluploalpath.mkdirs()) {
   				String newfilename = uuid + suffix;
   				if (i == 0) {
   					filepaths += attachment;
   					storepaths += newfilename;
   				} else {
   					filepaths += ";" + attachment;
   					storepaths += ";" + newfilename;
   				}
   				File newfile = new File(globaluploalpath, newfilename);
   				renamefile = file.renameTo(newfile);
   				if (!renamefile) {
   					renamemessage = file.getAbsolutePath() + "目录下的文件" + file.getName() + "重命名为"
   							+ newfile.getAbsolutePath() + "目录下的文件" + newfile.getName() + "失败了";
   					break;
   				}
   			}
   		}
   	
   		if (!renamefile) {
   				String message = "重命名文件失败";
   				sendResp.setGroupId(groupId);
   				sendResp.setStatus(PostheadStatus.BAD_REQUEST.value());
   				sendResp.setMessage(message);
   				sendResp.setDate(AppConst.dtFormat.format(new Date()));
   			return XstreamUtil.toXml(sendResp);
   		}

   		pes.setProcess(processInfos);
   		posthead.setProcesses(pes);
   		List<OrderResp> orderRespList=new ArrayList<OrderResp>();//子消息响应集合
   		for (RouteEntry to : toList) {
   			OrderResp orderResp = new OrderResp();//针对子消息的响应
   			String respXml = "";//针对一个to的响应xml
   			String id =  UUIDGenerator.getUUID();
//   						String msgType=null;
   			msg = "数据接收成功";
   			if (toList.size() == 1) {
   				id = groupId;
//   							msgType = AppConst.MsgType.SINGLE_MSG.value();
   			}else{
//   							msgType = AppConst.MsgType.SUB_MSG.value();
   			}
   			orderResp.setOrderId(id);
   			orderResp.setAdaptorcode(from.getAdaptorcode());
   			orderRespList.add(orderResp);
   			respXml = XstreamUtil.toXml(orderResp);
   			
   			SendFileData sendfileData = new SendFileData();
   			sendfileData.setOrderId(id);
   			sendfileData.setGroupId(groupId);
   			sendfileData.setSendNodecode(from.getNodecode());
   			sendfileData.setSendBusicode(adapterBase.getDataCode());
   			sendfileData.setSendAdaptorcode(from.getAdaptorcode());
   			sendfileData.setRecvNodecode(to.getNodecode());
   			sendfileData.setRecvAdaptorcode(from.getAdaptorcode());
   			sendfileData.setPosthead(XstreamUtil.toXml(posthead));
   			sendfileData.setResp(respXml);
   			sendfileData.setSendStatus(AppConst.SendStatus.READY.value());
   			sendfileData.setNotifyStatus(AppConst.NotifyStatus.READY.value());
   			sendfileData.setPriority(AppConst.Priority.NORMAL.value());
   			sendfileData.setPipeline(AppConst.FTP);
   			//                            fileData.setIp(ip);
   			sendfileData.setCreated(new Date());
   			sendfileData.setFilehome(globaluploalpath.getAbsolutePath());
   			sendfileData.setFilepaths(filepaths);
   			sendfileData.setStorepaths(storepaths);
   			sendfileData.setFilesize(size);
   			if (from.getNodecode().substring(0, 6).equals(to.getNodecode().substring(0,6))) {//取前六位看是否是跨节点传输
   				sendfileData.setCrossNode("0");
   			}else{
   				sendfileData.setCrossNode("1");
   			}
   			
   			if (from.getNodecode().substring(6, 7).equals(to.getNodecode().substring(6, 7))) {
   				sendfileData.setCrossNet("0");
   				sendfileData.setThroughGap("0");//不需要走网闸
   				sendfileData.setThroughGap("0");//不需需要走网闸
   			}else{
   				 if (AppTagEl.isInnerNet(from.getNodecode().substring(6, 7)) && !AppTagEl.isInnerNet(to.getNodecode())) {//from为内网 to为外网
   					 sendfileData.setCrossNet("1");
   				 }else{//from为外网，to为内网 需要走网闸
   					 sendfileData.setCrossNet("2");
   					 String gapNode=baseInfoService.getGapNode(localNode);
   					 
   					 if (gapNode!=null) {
   						 sendfileData.setThroughGap("1");//需要走网闸
   						 sendfileData.setOutGapNodeCode(gapNode);
   					 }else{
   						 sendfileData.setThroughGap("2");//需要刻盘
   						 sendfileData.setOutGapNodeCode(null);
   					 }
   				}
   			}
   			sendfileData.setAuditPerson(from.getAuditor());//审核人
   			sendfileData.setTrig(from.getSendTime());
   			sendfileData.setMetaData(null);
   			sendfileData.setFileItems(null);
   			RouteLog.setLocalStore(sendfileData, AppConst.YES, msg, AppConst.dtFormat.format(new Date()));//更新路由状态
   			//添加记录
   			fileDataList.add(sendfileData);
   			//we just assume this is always success...
   		}
   		sendFileDataService.insertBatch(fileDataList);//存数据库
   		sendResp.setOrderRespList(orderRespList);
		sendResp.setGroupId(groupId);
		sendResp.setStatus(PostheadStatus.OK.value());
		sendResp.setMessage("数据入库成功");
		sendResp.setDate(AppConst.dtFormat.format(new Date()));
   		return XstreamUtil.toXml(sendResp);
	} catch (Exception e) {
		logger.error("本地存储异常", e);
		sendResp.setGroupId(groupId);
		sendResp.setStatus(PostheadStatus.INTERNAL_SERVER_ERROR.value());
		sendResp.setMessage("数据入库失败"+e);
		sendResp.setDate(AppConst.dtFormat.format(new Date()));
   		try {
			return XstreamUtil.toXml(sendResp);
		} catch (Exception e1) {
			//
		}
	}
	return null;
	}

}
